package com.spring.springboot.interceptor;

import java.io.PrintWriter;
import java.security.SignatureException;
import java.util.Optional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.spring.springboot.entity.TokenInfoEntity;
import com.spring.springboot.jpa.TokenJPA;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;

/**
*@author LSY
*Time: 2018年12月17日下午1:55:56
*
*
*/

public class JwtTokenInterceptor implements HandlerInterceptor{

	@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
		
		if(request.getRequestURI().equals("/token") || RequestMethod.OPTIONS.toString().equals(request.getMethod())) {
			return true;
		}
		final String authHeader =request.getHeader("X-YAuth-Token");
		try {
			if(authHeader == null || authHeader.trim() == "") {
				throw new SignatureException("X-YAuth-Token");
			}
			final Claims claim = Jwts.parser().setSigningKey("YINGE AUthv1.0.0")
					.parseClaimsJws(authHeader).getBody();
			Optional<TokenInfoEntity> optional = getDAO(TokenJPA.class, request).findOne(new Specification<TokenInfoEntity>() {
				@Override
				public Predicate toPredicate(Root<TokenInfoEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
					criteriaQuery.where(criteriaBuilder.equal(root.get("appId"), claim.getSubject()));
					return null;
				}
			});
			TokenInfoEntity token = optional.get();
			String tokenStr = new String(token.getToken());
			if(tokenStr == null || "".equals(tokenStr.trim())) {
				throw new SignatureException("no found token info, please get token agin");
			}
			if(!tokenStr.equals(authHeader)) {
				throw new SignatureException("no found token info, please get token agin");
			}
		} catch (SignatureException | ExpiredJwtException e) {
			PrintWriter writer = response.getWriter();
			writer.write("need refresh token");
			writer.close();
			return false;
		}//出现异常时
        catch (final Exception e)
        {
            //输出对象
            PrintWriter writer = response.getWriter();
            //输出error消息
            writer.write(e.getMessage());
            writer.close();
            return false;
        }
		return true;
	}
	
	 /**
     * 根据传入的类型获取spring管理的对应dao
     * @param clazz 类型
     * @param request 请求对象
     * @param <T>
     * @return
     */
    private <T> T getDAO(Class<T> clazz,HttpServletRequest request) {
    	BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
    	return factory.getBean(clazz);
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}
